﻿using System;
using System.ComponentModel;
using System.Collections.Generic;

namespace FscNET.Tracer
{
    [Serializable]
    internal class BindingListEx<T> : BindingList<T>
    {
        private int _selectedIndex;

        public int SelectedIndex
        {
            get { return _selectedIndex; }
        }

        public T Selected { get { return this[_selectedIndex]; } }

        [field: NonSerialized]
        public event Action<object, EventArgs> SelectionChanged;

        public BindingListEx()
            : base()
        { }

        public BindingListEx(IList<T> list)
            : base(list)
        { }

        public void SetSelected(object sender, int index)
        {
            if (index < 0 || index >= Count)
                throw new ArgumentException(@"Value is out of range", "index");
            _selectedIndex = index;
            OnSelectionChanged(sender);
        }

        private void Move(T item, int sourceIndex, int destinationIndex)
        {
            if (sourceIndex < 0 || sourceIndex >= Count)
                throw new ArgumentException(@"Value is out of range", "sourceIndex");
            bool raiseListChangedEvents = RaiseListChangedEvents;
            try
            {
                RaiseListChangedEvents = false;
                Remove(item);
                InsertItem(destinationIndex, item);
                OnListChanged(new ListChangedEventArgs(ListChangedType.ItemMoved, destinationIndex, sourceIndex));
            }
            finally
            {
                RaiseListChangedEvents = raiseListChangedEvents;
            }
        }

        public void Move(T item, int destinationIndex)
        {
            if (destinationIndex < 0 || destinationIndex >= Count)
                throw new ArgumentException(@"Value is out of range", "destinationIndex");
            if (!Contains(item))
                throw new ArgumentException(@"Item is not in collection", "item");
            if (this[destinationIndex].Equals(item)) return;
            Move(item, IndexOf(item), destinationIndex);
        }

        public void Move(int sourceIndex, int destinationIndex)
        {
            if (sourceIndex < 0 || sourceIndex >= Count)
                throw new ArgumentException(@"Value is out of range", "sourceIndex");
            if (destinationIndex < 0 || destinationIndex >= Count)
                throw new ArgumentException(@"Value is out of range", "destinationIndex");
            if (sourceIndex == destinationIndex) return;
            Move(this[sourceIndex], sourceIndex, destinationIndex);
        }

        protected void OnSelectionChanged(object sender)
        {
            Action<object, EventArgs> handler = SelectionChanged;
            if (handler != null)
            {
                handler(sender ?? this, new EventArgs());
            }
        }
    }
}
